let currentMap = null;
let currentMapType = 'baidu';
let points = []; 
let markers = [];
let polyline = null;
let lastCenter = { lng: 116.404, lat: 39.915 };
let lastZoom = 12;

const mapTitle = document.getElementById('mapTitle');
const searchInput = document.getElementById('searchInput');
const searchBtn = document.getElementById('searchBtn');
const searchResults = document.getElementById('searchResults');
const addPointBtn = document.getElementById('addPointBtn');
const clearPointsBtn = document.getElementById('clearPointsBtn');
const exportBtn = document.getElementById('exportBtn');
const importBtn = document.getElementById('importBtn')
const importFileInput = document.getElementById('importFileInput');
const helpBtn = document.getElementById('helpBtn');
const closeHelpBtn = document.getElementById('closeHelpBtn');
const confirmHelpBtn = document.getElementById('confirmHelpBtn');
const helpModal = document.getElementById('helpModal');
const currentCoord = document.getElementById('currentCoord');
const totalLength = document.getElementById('totalLength');
const pointCount = document.getElementById('pointCount');
const mapContainer = document.getElementById('mapContainer');
const pointListContainer = document.getElementById('pointListContainer');
const noPointsMessage = document.getElementById('noPointsMessage');
const speedInput = document.getElementById('speedInput');
const manualAddPointModal = document.getElementById('manualAddPointModal');
const manualNameInput = document.getElementById('manualNameInput');
const manualLngInput = document.getElementById('manualLngInput');
const manualLatInput = document.getElementById('manualLatInput');
const manualAddPointConfirmBtn = document.getElementById('manualAddPointConfirmBtn');
const manualAddPointCancelBtn = document.getElementById('manualAddPointCancelBtn');
const copyright = document.createElement('footer');
	copyright.className = "text-center text-xs text-gray-400";
	copyright.textContent = "By map.204501.xyz Copyright © 2025";
	document.body.appendChild(copyright);

const mapSwitchButtons = [
	document.getElementById('baiduMapBtn'),
	document.getElementById('gaodeMapBtn'),
	document.getElementById('tiandituMapBtn'),
];

let currentSearchPoint = null; 
let baiduLocalSearchInstance = null;

let baiduMapClickHandler, baiduMapMouseMoveHandler;
let gaodeMapClickHandler, gaodeMapMouseMoveHandler;
let tiandituMapClickHandler, tiandituMapMouseMoveHandler;


function renderPointList() {
	pointListContainer.innerHTML = ''; 
	if (points.length === 0) {
		if (!pointListContainer.contains(noPointsMessage)) {
				pointListContainer.appendChild(noPointsMessage);
		}
		noPointsMessage.style.display = 'block';
		return;
	}
	noPointsMessage.style.display = 'none';

	points.forEach((point) => {
		const pointItemDiv = document.createElement('div');
		pointItemDiv.className = 'p-2 bg-white border border-gray-200 rounded-md shadow-sm flex justify-between items-start space-x-2';
		pointItemDiv.dataset.pointId = point.id;

		const infoWrapper = document.createElement('div');
		infoWrapper.className = 'space-y-1 flex-grow';

		const nameGroup = document.createElement('div');
		nameGroup.className = 'flex items-center space-x-2';
		const nameLabel = document.createElement('label');
		nameLabel.className = 'text-xs font-medium w-10 text-gray-600 shrink-0';
		nameLabel.textContent = `名称:`;
		nameLabel.htmlFor = `pointName-${point.id}`;
		const nameInput = document.createElement('input');
		nameInput.type = 'text';
		nameInput.id = `pointName-${point.id}`;
		nameInput.value = point.name;
		nameInput.className = 'point-input flex-grow';
		nameInput.title = "点位名称";
		nameInput.addEventListener('change', (e) => handlePointDataChange(point.id, 'name', e.target.value));
		nameGroup.appendChild(nameLabel);
		nameGroup.appendChild(nameInput);

		const lngGroup = document.createElement('div');
		lngGroup.className = 'flex items-center space-x-2';
		const lngLabel = document.createElement('label');
		lngLabel.className = 'text-xs font-medium w-10 text-gray-600 shrink-0';
		lngLabel.textContent = `经度:`;
		lngLabel.htmlFor = `pointLng-${point.id}`;
		const lngInput = document.createElement('input');
		lngInput.type = 'number';
		lngInput.id = `pointLng-${point.id}`;
		lngInput.step = 'any';
		lngInput.value = point.lng.toFixed(6);
		lngInput.className = 'point-input flex-grow';
		lngInput.title = "经度";
		lngInput.addEventListener('change', (e) => handlePointDataChange(point.id, 'lng', e.target.value));
		lngGroup.appendChild(lngLabel);
		lngGroup.appendChild(lngInput);
		
		const latGroup = document.createElement('div');
		latGroup.className = 'flex items-center space-x-2';
		const latLabel = document.createElement('label');
		latLabel.className = 'text-xs font-medium w-10 text-gray-600 shrink-0';
		latLabel.textContent = `纬度:`;
		latLabel.htmlFor = `pointLat-${point.id}`;
		const latInput = document.createElement('input');
		latInput.type = 'number';
		latInput.id = `pointLat-${point.id}`;
		latInput.step = 'any';
		latInput.value = point.lat.toFixed(6);
		latInput.className = 'point-input flex-grow';
		latInput.title = "纬度";
		latInput.addEventListener('change', (e) => handlePointDataChange(point.id, 'lat', e.target.value));
		latGroup.appendChild(latLabel);
		latGroup.appendChild(latInput);

		infoWrapper.appendChild(nameGroup);
		infoWrapper.appendChild(lngGroup);
		infoWrapper.appendChild(latGroup);

		const deleteBtn = document.createElement('button');
		deleteBtn.innerHTML = '<i class="fa fa-trash-o mr-1"></i>删除';
		deleteBtn.className = 'text-xs text-red-500 hover:text-red-700 transition-colors py-1 px-2 rounded-md border border-red-300 hover:bg-red-50 self-center shrink-0 flex items-center';
		deleteBtn.title = "删除此点";
		deleteBtn.addEventListener('click', () => handleDeletePoint(point.id));
		
		pointItemDiv.appendChild(infoWrapper);
		pointItemDiv.appendChild(deleteBtn);
		pointListContainer.appendChild(pointItemDiv);
	});
}

function handlePointDataChange(pointId, field, value) {
	const pointIndex = points.findIndex(p => p.id === pointId);
	if (pointIndex === -1) return;

	let needsMapUpdate = false;
	if (field === 'name') {
		points[pointIndex].name = String(value).trim() || `点${pointIndex + 1}`;
		needsMapUpdate = true;
	} else if (field === 'lng' || field === 'lat') {
		const newValue = parseFloat(value); 
		if (isNaN(newValue)) { 
			alert(`无效的${field === 'lng' ? '经度' : '纬度'}值！将恢复原始值。`); 
			renderPointList(); 
			return; 
		}
		if (points[pointIndex][field].toFixed(6) !== newValue.toFixed(6)) {
			points[pointIndex][field] = newValue;
			needsMapUpdate = true;
		}
	}
	
	if (needsMapUpdate) {
		updateMapDisplay(false); 
	}
}

function handleDeletePoint(pointId) {
	points = points.filter(p => p.id !== pointId);
	renderPointList();
	updateMapDisplay(false); 
}

function initMap(mapType) {
	if (currentMap) {
		try {
			switch (currentMapType) {
				case 'baidu':
					lastCenter = { lng: currentMap.getCenter().lng, lat: currentMap.getCenter().lat };
					lastZoom = currentMap.getZoom();
					if (baiduMapClickHandler) currentMap.removeEventListener('click', baiduMapClickHandler);
					if (baiduMapMouseMoveHandler) currentMap.removeEventListener('mousemove', baiduMapMouseMoveHandler);
					break;
				case 'gaode':
					if (currentMap.getCenter && typeof currentMap.getCenter === 'function' && currentMap.getCenter()) {
						lastCenter = { lng: currentMap.getCenter().getLng(), lat: currentMap.getCenter().getLat() };
						lastZoom = currentMap.getZoom();
					}
					if (gaodeMapClickHandler) currentMap.off('click', gaodeMapClickHandler);
					if (gaodeMapMouseMoveHandler) currentMap.off('mousemove', gaodeMapMouseMoveHandler);
					if (typeof currentMap.destroy === 'function') {
						currentMap.destroy();
					}
					break;
				case 'tianditu':
						if (currentMap.getCenter && typeof currentMap.getCenter === 'function' && currentMap.getCenter()) {
						lastCenter = { lng: currentMap.getCenter().getLng(), lat: currentMap.getCenter().getLat() };
						lastZoom = currentMap.getZoom();
					}
					if (tiandituMapClickHandler) currentMap.removeEventListener("click", tiandituMapClickHandler);
					if (tiandituMapMouseMoveHandler) currentMap.removeEventListener("mousemove", tiandituMapMouseMoveHandler);
					break;
			}
		} catch (e) { console.warn(`Error cleaning up old map (${currentMapType}):`, e); }
		currentMap = null; 
	}
	
const oldMapContainer = document.getElementById('mapContainer');
const newMapContainer = oldMapContainer.cloneNode(false);
oldMapContainer.parentNode.replaceChild(newMapContainer, oldMapContainer);
window.mapContainer = document.getElementById('mapContainer');

currentMapType = mapType;
updateMapSwitchButtons();

try {
switch (mapType) {
	case 'baidu': initBaiduMap(); mapTitle.textContent = "百度地图路线追踪"; break;
	case 'gaode': initGaodeMap(); mapTitle.textContent = "高德地图路线追踪"; break;
	case 'tianditu': initTiandituMap(); mapTitle.textContent = "天地图路线追踪"; break;
}
if(currentMap) { 
	updateMapDisplay(true); 
	renderPointList(); 
} else {
	console.error(`${mapType} map object (currentMap) is null!`);
}
} catch (mapInitError) {
console.error(`Error initializing ${mapType} map:`, mapInitError);
mapContainer.innerHTML = `<div class="p-4 text-red-500">初始化 ${mapType} 地图失败。详情请查看控制台。</div>`;
}
}

function initBaiduMap() {
	currentMap = new BMap.Map("mapContainer", {enableMapClick: false});
	currentMap.centerAndZoom(new BMap.Point(lastCenter.lng, lastCenter.lat), lastZoom);
	currentMap.enableScrollWheelZoom(true);
	currentMap.addControl(new BMap.NavigationControl());
	currentMap.addControl(new BMap.ScaleControl());

	baiduMapClickHandler = function(e) {
		if(e.overlay) { return; }
		const pointName = searchInput.value && currentSearchPoint && e.point.lng.toFixed(6) === currentSearchPoint.lng.toFixed(6) && e.point.lat.toFixed(6) === currentSearchPoint.lat.toFixed(6) 
						? currentSearchPoint.name 
						: `点${points.length + 1}`;
		addUniversalPoint(pointName, e.point.lng, e.point.lat);
	};
	currentMap.addEventListener('click', baiduMapClickHandler);

	baiduMapMouseMoveHandler = function(e) {
		currentCoord.textContent = `坐标: ${e.point.lng.toFixed(6)}, ${e.point.lat.toFixed(6)}`;
	};
	currentMap.addEventListener('mousemove', baiduMapMouseMoveHandler);

	setTimeout(() => {
		if (currentMap) currentMap.enableScrollWheelZoom(true);
	}, 100);
}

function initGaodeMap() {
	currentMap = new AMap.Map("mapContainer", {
		zoom: lastZoom, center: [lastCenter.lng, lastCenter.lat], viewMode: '2D'
	});
	currentMap.addControl(new AMap.ToolBar());
	currentMap.addControl(new AMap.Scale());
	
	gaodeMapClickHandler = function(e) {
			if (e.target !== currentMap && e.target.CLASS_NAME && e.target.CLASS_NAME.indexOf("Marker") > -1) {
			return;
		}
		const pointName = searchInput.value && currentSearchPoint && e.lnglat.getLng().toFixed(6) === currentSearchPoint.lng.toFixed(6) && e.lnglat.getLat().toFixed(6) === currentSearchPoint.lat.toFixed(6) 
						? currentSearchPoint.name 
						: `点${points.length + 1}`;
		addUniversalPoint(pointName, e.lnglat.getLng(), e.lnglat.getLat());
	};
	currentMap.on('click', gaodeMapClickHandler);

	gaodeMapMouseMoveHandler = function(e) {
		currentCoord.textContent = `坐标: ${e.lnglat.getLng().toFixed(6)}, ${e.lnglat.getLat().toFixed(6)}`;
	};
	currentMap.on('mousemove', gaodeMapMouseMoveHandler);
}

function initTiandituMap() {
	if (typeof T === 'undefined' || typeof T.Map === 'undefined') {
		throw new Error("Tianditu API not loaded.");
	}
	currentMap = new T.Map("mapContainer");
	currentMap.centerAndZoom(new T.LngLat(lastCenter.lng, lastCenter.lat), lastZoom);
	let ctrl = new T.Control.Zoom();
	ctrl.setPosition(T_ANCHOR_BOTTOM_RIGHT);
	currentMap.addControl(ctrl);
	
	tiandituMapClickHandler = function(e) {
		let targetIsMarker = e.target && (e.target.CLASS_NAME === "T.Marker" || (e.target.className && String(e.target.className).includes("tdt-marker-icon")) || (e.target.parentNode && e.target.parentNode.className && String(e.target.parentNode.className).includes("tdt-marker-icon")));
		if (targetIsMarker) { return;}
		const pointName = searchInput.value && currentSearchPoint && e.lnglat.getLng().toFixed(6) === currentSearchPoint.lng.toFixed(6) && e.lnglat.getLat().toFixed(6) === currentSearchPoint.lat.toFixed(6) 
						? currentSearchPoint.name 
						: `点${points.length + 1}`;
		addUniversalPoint(pointName, e.lnglat.getLng(), e.lnglat.getLat());
	};
	currentMap.addEventListener("click", tiandituMapClickHandler);

	tiandituMapMouseMoveHandler = function(e) {
			currentCoord.textContent = `坐标: ${e.lnglat.getLng().toFixed(6)}, ${e.lnglat.getLat().toFixed(6)}`;
	};
	currentMap.addEventListener("mousemove", tiandituMapMouseMoveHandler);
}

function addUniversalPoint(name, lng, lat) {
	const newPoint = {
		id: Date.now().toString(36) + Math.random().toString(36).substr(2, 5),
		name: name || `点${points.length + 1}`,
		lng: lng,
		lat: lat,
		order: Date.now() + Math.random()
	};
	points.push(newPoint);
	currentSearchPoint = null; 
	searchInput.value = ''; 
	updateMapDisplay(false); 
	renderPointList(); 
}

function updateMapDisplay(adjustView = true) {
	clearOverlaysFromCurrentMap(); 
	markers = []; 
	polyline = null; 

	if (!currentMap) { 
		updateStats(); 
		renderPointList(); 
		return;
	}
	
	if (points.length === 0) {
		updateStats();
		renderPointList(); 
		return;
	}

	let pathForPolyline = [];
	points.forEach((p, index) => { 
		let marker;
		let mapPoint;
		let labelText = p.name; 
		const currentPointId = p.id; 

		switch (currentMapType) {
			case 'baidu':
				let iconColorBaidu = "#1296db"; 
				if (index === 0) iconColorBaidu = "#d9250e"; 
				else if (index === points.length - 1 && points.length > 1) iconColorBaidu = "#1afa29"; 
				mapPoint = new BMap.Point(p.lng, p.lat);
				let bIcon = new BMap.Symbol(BMap_Symbol_SHAPE_POINT, { 
					scale: 1.5, fillColor: iconColorBaidu, strokeColor: iconColorBaidu, fillOpacity: 0.8
				});
				marker = new BMap.Marker(mapPoint, {icon: bIcon, title: p.name});
				marker.enableDragging();
				marker.addEventListener('dragend', function(e) {
					const draggedPointIndex = points.findIndex(pt => pt.id === currentPointId);
					if (draggedPointIndex !== -1) {
						points[draggedPointIndex].lng = e.point.lng;
						points[draggedPointIndex].lat = e.point.lat;
						updateMapDisplay(false); 
						renderPointList(); 
					}
				});
				currentMap.addOverlay(marker);
				const label = new BMap.Label(labelText, {offset: new BMap.Size(20, -10)});
				label.setStyle({ border: "none", background: "none", color: "#333", fontWeight: "bold", fontSize: "12px" });
				marker.setLabel(label);
				break;
			case 'gaode':
				mapPoint = new AMap.LngLat(p.lng, p.lat);
				let gaodeMarkerColor = "#1296db"; 
				if (index === 0) gaodeMarkerColor = "#d9250e"; 
				else if (index === points.length - 1 && points.length > 1) gaodeMarkerColor = "#1afa29"; 

				const markerDotHtml = `<div style="width:12px; height:12px; background-color:${gaodeMarkerColor}; border-radius:50%; border:2px solid #fff; box-shadow:0 0 5px rgba(0,0,0,0.3);"></div>`;
				const labelHtmlGaode = `<div style="position:relative; background:#58A9FA; color:white; padding:4px 8px; font-size:12px; border-radius:4px; box-shadow:0 1px 3px rgba(0,0,0,0.3); white-space:nowrap;">${labelText}<div style="position:absolute; bottom:-6px; left:calc(50% - 6px); width:0; height:0; border-left:6px solid transparent; border-right:6px solid transparent; border-top:6px solid #58A9FA;"></div></div>`;

				marker = new AMap.Marker({
					position: mapPoint,
					content: markerDotHtml,
					anchor: 'center',
					title: p.name, 
					draggable: true,
					label: {
						content: labelHtmlGaode,
						direction: 'top', 
						offset: new AMap.Pixel(0, -10) 
					}
				});
				marker.on('dragend', function(e) {
					const draggedPointIndex = points.findIndex(pt => pt.id === currentPointId);
					if (draggedPointIndex !== -1) {
						points[draggedPointIndex].lng = e.lnglat.getLng();
						points[draggedPointIndex].lat = e.lnglat.getLat();
						updateMapDisplay(false);
						renderPointList();
					}
				});
				currentMap.add(marker);
				break;
			case 'tianditu':
				if (typeof T === 'undefined') { return; }
				mapPoint = new T.LngLat(p.lng, p.lat);
				let tIconUrl = "assets/images/blue.png";
				if (index === 0) tIconUrl = "assets/images/red.png";
				else if (index === points.length - 1 && points.length > 1) tIconUrl = "assets/images/green.png";
				
				let tIcon = new T.Icon({ iconUrl: tIconUrl, iconSize: new T.Point(19, 27), iconAnchor: new T.Point(10, 25) });
				marker = new T.Marker(mapPoint, {icon: tIcon, title: p.name});
				currentMap.addOverLay(marker); 
				try {
					marker.enableDragging(); 
					marker.addEventListener("dragend", function(evt) {
						const draggedPointIndex = points.findIndex(pt => pt.id === currentPointId);
						if (draggedPointIndex !== -1) {
							points[draggedPointIndex].lng = evt.lnglat.getLng();
							points[draggedPointIndex].lat = evt.lnglat.getLat();
							updateMapDisplay(false);
							renderPointList();
						}
					});
				} catch (e) { console.warn(`Tianditu: Error enabling dragging (marker might not support it or API issue).`, e); }
				const tLabel = new T.Label({text: labelText, position: mapPoint, offset: new T.Point(15, -15)});
				if(tLabel.setBorderLine) tLabel.setBorderLine(false); 
				if(tLabel.setBackgroundColor) tLabel.setBackgroundColor("none"); 
				if(tLabel.setFontColor) tLabel.setFontColor("#333");
				currentMap.addOverLay(tLabel);
				break;
		}
		markers.push(marker);
		pathForPolyline.push(mapPoint);
	});

	if (points.length >= 2) {
			switch (currentMapType) {
			case 'baidu': polyline = new BMap.Polyline(pathForPolyline, { strokeColor: '#165DFF', strokeWeight: 4, strokeOpacity: 0.8 }); currentMap.addOverlay(polyline); break;
			case 'gaode': polyline = new AMap.Polyline({ path: pathForPolyline, strokeColor: '#165DFF', strokeWeight: 4, strokeOpacity: 0.8, lineJoin: 'round', lineCap: 'round' }); currentMap.add(polyline); break;
			case 'tianditu': 
				if (typeof T === 'undefined') { return; }
				polyline = new T.Polyline(pathForPolyline, { color: '#165DFF', weight: 4, opacity: 0.8, lineStyle:"solid" }); currentMap.addOverLay(polyline); break;
		}
	}
	if (adjustView && points.length > 0 && pathForPolyline.length > 0) {
			setMapView(pathForPolyline); 
	}
	updateStats();
}

function clearOverlaysFromCurrentMap() {
	if (!currentMap) return;
	try {
		switch (currentMapType) {
			case 'baidu': currentMap.clearOverlays(); break;
			case 'gaode': currentMap.clearMap(); break;
			case 'tianditu': if (typeof T !== 'undefined' && currentMap.clearOverLays) currentMap.clearOverLays(); break; 
		}
	} catch (e) { console.error(`Error clearing overlays for ${currentMapType}`, e); }
	markers = []; polyline = null;
}

function setMapView(mapPointsToView) {
	if (!currentMap || !mapPointsToView || mapPointsToView.length === 0) return;
	try {
		if (mapPointsToView.length === 1) {
			const singleMapPoint = mapPointsToView[0];
			const zoomLevel = currentMap.getZoom() > 15 ? currentMap.getZoom() : 15;
			switch (currentMapType) {
				case 'baidu': currentMap.centerAndZoom(singleMapPoint, zoomLevel); break;
				case 'gaode': currentMap.setZoomAndCenter(zoomLevel, singleMapPoint); break;
				case 'tianditu': if (typeof T !== 'undefined') currentMap.centerAndZoom(singleMapPoint, zoomLevel); break;
			}
		} else { 
			switch (currentMapType) {
				case 'baidu': currentMap.setViewport(mapPointsToView); break;
				case 'gaode': currentMap.setFitView(markers.concat(polyline || [])); break; 
				case 'tianditu': if (typeof T !== 'undefined') currentMap.setViewport(mapPointsToView.map(p => new T.LngLat(p.lng || p.getLng(), p.lat || p.getLat()))); break;
			}
		}
		
		if (currentMap.getCenter && typeof currentMap.getCenter === 'function' && currentMap.getCenter()) { 
			if (currentMapType === 'baidu') {
				lastCenter = { lng: currentMap.getCenter().lng, lat: currentMap.getCenter().lat }; lastZoom = currentMap.getZoom();
			} else if (currentMapType === 'gaode' || currentMapType === 'tianditu') {
				if(currentMap.getCenter().getLng && currentMap.getCenter().getLat){ 
					lastCenter = { lng: currentMap.getCenter().getLng(), lat: currentMap.getCenter().getLat() }; lastZoom = currentMap.getZoom();
				}
			}
		}
	} catch (e) { console.error("Error setting map view:", e); }
}

function searchPlace() { 
	const keyword = searchInput.value.trim();
	if (!keyword) { searchResults.innerHTML = ''; searchResults.classList.add('hidden'); return; }
	searchResults.innerHTML = '<div class="p-2 text-gray-500">正在搜索...</div>';
	searchResults.classList.remove('hidden');

	switch (currentMapType) {
		case 'baidu':
			baiduLocalSearchInstance = new BMap.LocalSearch(currentMap, {
				onSearchComplete: displayBaiduSearchResults 
			});
			baiduLocalSearchInstance.search(keyword);
			break;
		case 'gaode':
			if (typeof AMap === 'undefined' || !AMap.PlaceSearch) {
				searchResults.innerHTML = '<div class="p-2 text-red-500">高德地图搜索服务未加载</div>';
				return;
			}
			const placeSearchGaode = new AMap.PlaceSearch({ map: currentMap, pageSize: 10, autoFitView: false });
			placeSearchGaode.search(keyword, function(status, result) {
				if (status === 'complete' && result.poiList && result.poiList.pois.length > 0) {
					displayGaodeSearchResults(result.poiList.pois);
				} else {
					searchResults.innerHTML = `<div class="p-2 text-gray-500">未找到结果 (${status === 'no_data' ? '无数据' : status})</div>`;
				}
			});
			break;
		case 'tianditu':
			let mapBound = "116.02524,39.83833,116.65592,39.99185";
			try {
				if (currentMap && currentMap.getBounds) {
					const bounds = currentMap.getBounds();
					if (bounds && bounds.getSouthWest && bounds.getNorthEast) {
						const sw = bounds.getSouthWest();
						const ne = bounds.getNorthEast();
						mapBound = `${sw.getLng()},${sw.getLat()},${ne.getLng()},${ne.getLat()}`;
					}
				}
			} catch (e) {}
			const postStr = encodeURIComponent(JSON.stringify({
				keyWord: keyword,
				level: 12,
				mapBound: mapBound,
				queryType: 1,
				start: 0,
				count: 10
			}));
			const tk = "c2a12fdc9c5ceebf0c9bd3bde6f44172";
			const url = `https://api.tianditu.gov.cn/v2/search?postStr=${postStr}&type=query&tk=${tk}`;
			fetch(url)
				.then(res => res.json())
				.then(data => {
					if (data && data.pois && data.pois.length > 0) {
						displayTiandituSearchResults(data.pois, false);
					} else {
						searchResults.innerHTML = '<div class="p-2 text-gray-500">未找到结果 (天地图)</div>';
					}
				})
				.catch(() => {
					searchResults.innerHTML = '<div class="p-2 text-red-500">天地图搜索服务请求失败</div>';
				});
			break;
	}
}
function displayBaiduSearchResults(results) { 
	searchResults.innerHTML = ''; 
	if (!baiduLocalSearchInstance || baiduLocalSearchInstance.getStatus() !== BMAP_STATUS_SUCCESS || results.getCurrentNumPois() === 0) {
		searchResults.innerHTML = '<div class="p-2 text-gray-500">未找到结果或搜索错误</div>'; return;
	}
	for (let i = 0; i < results.getCurrentNumPois(); i++) {
		const poi = results.getPoi(i);
		addSearchResultItem(poi.title, poi.address, {lng: poi.point.lng, lat: poi.point.lat});
	}
}
function displayGaodeSearchResults(pois) {
	searchResults.innerHTML = '';
	if (pois.length === 0) { searchResults.innerHTML = '<div class="p-2 text-gray-500">未找到结果</div>'; return; }
	pois.forEach(poi => {
		addSearchResultItem(poi.name, poi.address, {lng: poi.location.getLng(), lat: poi.location.getLat()});
	});
}
function displayTiandituSearchResults(data, isSuggestion = false) {
	searchResults.innerHTML = '';
	if (!data || data.length === 0) { searchResults.innerHTML = '<div class="p-2 text-gray-500">未找到结果</div>'; return; }
	let itemsAdded = 0;
	data.forEach(item => {
		let title, address, coords;
			if (isSuggestion) { 
			title = item.name;
			address = item.address || (item.admins && item.admins.length > 0 ? item.admins.map(a=>a.name).join(' ') : (item.district || ""));
			if (item.lonlat) { 
				if (typeof item.lonlat === 'string') {
					const parts = String(item.lonlat).split(','); 
					if (parts.length === 2) coords = {lng: parseFloat(parts[0]), lat: parseFloat(parts[1])}; 
				} else if (typeof item.lonlat.lng === 'number' && typeof item.lonlat.lat === 'number') { 
					coords = {lng: item.lonlat.lng, lat: item.lonlat.lat};
				}
			} else if (item.lnglat && typeof item.lnglat.lng === 'number' && typeof item.lnglat.lat === 'number') { 
					coords = {lng: item.lnglat.lng, lat: item.lnglat.lat};
			}
		} else { 
			title = item.name; address = item.address;
			if (item.lonlat && typeof item.lonlat.getLng === 'function') coords = {lng: item.lonlat.getLng(), lat: item.lonlat.getLat()}; 
			else if (item.lnglat && typeof item.lnglat.lng === 'number' && typeof item.lnglat.lat === 'number') coords = {lng: item.lnglat.lng, lat: item.lnglat.lat};
			else if (typeof item.lonlat === 'string') { 
					const parts = String(item.lonlat).split(','); 
					if (parts.length === 2) coords = {lng: parseFloat(parts[0]), lat: parseFloat(parts[1])}; 
			}
		}
		if (title && coords && !isNaN(coords.lng) && !isNaN(coords.lat)) { addSearchResultItem(title, address, coords); itemsAdded++; }
	});
	if (itemsAdded === 0) searchResults.innerHTML = '<div class="p-2 text-gray-500">无有效结果或坐标信息</div>';
}

function addSearchResultItem(title, address, pointCoords) {
	const resultItem = document.createElement('div');
	resultItem.className = 'p-2 hover:bg-gray-100 cursor-pointer transition-all-300';
	resultItem.innerHTML = `<div class="font-medium text-sm">${title}</div><div class="text-xs text-gray-500">${address || 'N/A'}</div>`;
	resultItem.addEventListener('click', function() {
		if (!pointCoords || typeof pointCoords.lng !== 'number' || typeof pointCoords.lat !== 'number') {
			alert("该搜索结果无精确坐标。"); searchResults.innerHTML = ''; searchResults.classList.add('hidden'); return;
		}
		currentSearchPoint = { name: title, lng: pointCoords.lng, lat: pointCoords.lat };
		searchInput.value = title;

		let mapPointToCenter;
		const zoomLevel = 15; 
		switch(currentMapType) {
			case 'baidu': mapPointToCenter = new BMap.Point(pointCoords.lng, pointCoords.lat); break;
			case 'gaode': mapPointToCenter = new AMap.LngLat(pointCoords.lng, pointCoords.lat); break;
			case 'tianditu': 
				if (typeof T === 'undefined') { alert("天地图API未加载"); return; }
				mapPointToCenter = new T.LngLat(pointCoords.lng, pointCoords.lat); break;
		}

		if (currentMap && mapPointToCenter) {
			if (currentMapType === 'gaode') {
				currentMap.setZoomAndCenter(zoomLevel, mapPointToCenter);
			} else { 
				currentMap.centerAndZoom(mapPointToCenter, zoomLevel);
			}
			lastCenter = { lng: pointCoords.lng, lat: pointCoords.lat };
			lastZoom = zoomLevel;
		}
		
		searchResults.innerHTML = ''; 
		searchResults.classList.add('hidden');
	});
	searchResults.appendChild(resultItem);
}

addPointBtn.addEventListener('click', function() {
	if (currentSearchPoint) {
		addUniversalPoint(currentSearchPoint.name, currentSearchPoint.lng, currentSearchPoint.lat);
	} else if (currentMap && currentMap.getCenter()) {
		let centerLng, centerLat;
			try {
			if (currentMapType === 'baidu') {
				centerLng = currentMap.getCenter().lng;
				centerLat = currentMap.getCenter().lat;
			} else if (currentMapType === 'gaode' || currentMapType === 'tianditu'){ 
				centerLng = currentMap.getCenter().getLng();
				centerLat = currentMap.getCenter().getLat();
			} else {
				throw new Error("Map type not supported for getCenter here or getCenter failed.");
			}
			addUniversalPoint(`点${points.length + 1}`, centerLng, centerLat);
		} catch (e) {
				console.error("Error getting map center for AddPointBtn:", e);
				alert("无法获取当前地图中心点。请先通过地图点击或搜索选择一个点。");
		}
	} else {
			alert("请先通过地图点击或搜索选择一个点。");
	}
});

clearPointsBtn.addEventListener('click', function() {
	points = []; currentSearchPoint = null; 
	searchInput.value = '';
	updateMapDisplay(false); 
	renderPointList(); 
});

function updateStats() {
	pointCount.textContent = points.length;
	let length = 0;
	if (points.length >= 2 && currentMap) {
		for (let i = 0; i < points.length - 1; i++) {
			const p1 = points[i], p2 = points[i+1]; let dist = 0;
			try {
				switch (currentMapType) {
					case 'baidu': dist = currentMap.getDistance(new BMap.Point(p1.lng, p1.lat), new BMap.Point(p2.lng, p2.lat)); break;
					case 'gaode': dist = AMap.GeometryUtil.distance(new AMap.LngLat(p1.lng, p1.lat), new AMap.LngLat(p2.lng, p2.lat)); break;
					case 'tianditu': 
						if (typeof T === 'undefined' || !T.LngLat ) break; 
						dist = (new T.LngLat(p1.lng, p1.lat)).distanceTo(new T.LngLat(p2.lng, p2.lat)); break;
				}
			} catch (e) { console.warn("Error calculating distance:", e); dist = 0;}
			length += dist;
		}
		length = (length / 1000);
	}
	totalLength.textContent = `${length > 0 ? length.toFixed(2) : '0'} 千米`;

	const speedInput = document.getElementById('speedInput');
	const totalTime = document.getElementById('totalTime');
	let speed = speedInput ? parseFloat(speedInput.value) : 0;
	if (!speed || speed <= 0) speed = 60;
	let hours = length / speed;
	if (isNaN(hours) || hours <= 0) {
		totalTime.textContent = '0小时0分';
	} else {
		const h = Math.floor(hours);
		const m = Math.round((hours - h) * 60);
		totalTime.textContent = `${h}小时${m}分`;
	}
}

exportBtn.addEventListener('click', function() {
	if (points.length === 0) { alert('没有点位数据可导出！'); return; }
	let csvContent = '名称,经度,纬度\n';
	points.forEach((point, index) => {
		const nameForCsv = point.name.includes(',') ? `"${point.name}"` : point.name; 
		csvContent += `${nameForCsv},${point.lng.toFixed(6)},${point.lat.toFixed(6)}\n`;
	});
	const blob = new Blob([String.fromCharCode(0xFEFF), csvContent], {type: 'text/csv;charset=utf-8;'}); 
	const link = document.createElement('a');
	const url = URL.createObjectURL(blob);
	link.setAttribute('href', url);
	link.setAttribute('download', `路线点位_${currentMapType}_${new Date().toISOString().slice(0, 10)}.csv`);
	link.style.visibility = 'hidden';
	document.body.appendChild(link); link.click(); document.body.removeChild(link);
	URL.revokeObjectURL(url);
});

importBtn.addEventListener('click', function() {
	importFileInput.click();
});

importFileInput.addEventListener('change', function(event) {
	const file = event.target.files[0];
	if (!file) return;
	const reader = new FileReader();
	reader.onload = function(e) {
let csvString = e.target.result;
const isMessy = /�/.test(csvString);
if (isMessy && window.TextDecoder) {
	const fr2 = new FileReader();
	fr2.onload = function(e2) {
		try {
			const decoder = new TextDecoder('gbk');
			const text = decoder.decode(e2.target.result);
			parseCSVAndAddPoints(text);
		} catch (err) {
			alert('文件编码无法识别，建议用UTF-8格式保存后再导入。');
		}
	};
	fr2.readAsArrayBuffer(file);
} else {
	if (csvString.charCodeAt(0) === 0xFEFF) {
		csvString = csvString.slice(1);
	}
	parseCSVAndAddPoints(csvString);
}
};
reader.onerror = function() {
alert('文件读取失败，请重试！');
};
reader.readAsText(file, 'utf-8');
});

function handleFileImport(event) {
	const file = event.target.files[0];
	if (!file) {
		return;
	}
	if (!file.name.toLowerCase().endsWith('.csv')) {
		alert('请选择一个 CSV 文件进行导入！');
		event.target.value = null;
		return;
	}

	const reader = new FileReader();
	reader.onload = function(e) {
		try {
			parseCSVAndAddPoints(e.target.result);
		} catch (error) {
			console.error("Error parsing CSV:", error);
			alert(`导入CSV文件时出错: ${error.message}`);
		}
		event.target.value = null;
	};
	reader.onerror = function() {
		alert('读取文件失败！');
		event.target.value = null;
	};
	reader.readAsText(file);
}

function parseCSVAndAddPoints(csvString) {
	const lines = csvString.split(/\r\n|\n/);
	const newPoints = [];
	let importedCount = 0;
	let skippedCount = 0;

	lines.forEach((line, index) => {
		line = line.trim();
		if (line === '') return;

		if (index === 0) {
			const lowerLine = line.toLowerCase();
			if (lowerLine.includes('name') || lowerLine.includes('经度') || lowerLine.includes('纬度') || 
				lowerLine.includes('longitude') || lowerLine.includes('latitude') || lowerLine.includes('序号') || lowerLine.includes('名称')) {
				console.log("Skipping header row:", line);
				return; 
			}
		}
		
		let parts;
		let name = `导入点${points.length + newPoints.length + 1}`;
		let lng, lat;

		if (line.startsWith('"')) {
			const endIndex = line.indexOf('"', 1);
			if (endIndex > 0) {
				name = line.substring(1, endIndex);
				const rest = line.substring(endIndex + 1).trim();
				if (rest.startsWith(',')) {
					parts = rest.substring(1).split(',').map(p => p.trim());
				} else {
						parts = [];
				}
				if (parts.length >= 2) {
					lng = parseFloat(parts[0]);
					lat = parseFloat(parts[1]);
				}
			} else {
				parts = line.split(',').map(p => p.trim());
			}
		} else {
			parts = line.split(',').map(p => p.trim());
		}


		if (!lng && !lat) {
			if (parts.length === 2) {
				lng = parseFloat(parts[0]);
				lat = parseFloat(parts[1]);
			} else if (parts.length >= 3) {
				name = parts[0];
				lng = parseFloat(parts[1]);
				lat = parseFloat(parts[2]);
			} else {
				console.warn(`Skipping line ${index + 1} due to incorrect column count: ${line}`);
				skippedCount++;
				return;
			}
		}


		if (isNaN(lng) || isNaN(lat)) {
			console.warn(`Skipping line ${index + 1} due to invalid coordinates: ${line}`);
			skippedCount++;
			return;
		}
			if (lat < -90 || lat > 90 || lng < -180 || lng > 180) {
			console.warn(`Skipping line ${index + 1} due to out-of-range coordinates: ${line}`);
			skippedCount++;
			return;
		}


		newPoints.push({
			id: Date.now().toString(36) + Math.random().toString(36).substr(2, 5) + `-${index}`,
			name: name,
			lng: lng,
			lat: lat,
			order: Date.now() + Math.random()
		});
		importedCount++;
	});

	if (newPoints.length > 0) {
		points.push(...newPoints);
		renderPointList();
		updateMapDisplay(true);
		alert(`成功导入 ${importedCount} 个点位。${skippedCount > 0 ? `跳过 ${skippedCount} 行无效数据。` : ''}`);
	} else {
		alert(`未能从文件中导入任何有效点位。${skippedCount > 0 ? `跳过 ${skippedCount} 行无效数据。` : ''} 请检查文件格式和内容。`);
	}
}

helpBtn.addEventListener('click', () => helpModal.classList.remove('hidden'));
closeHelpBtn.addEventListener('click', () => helpModal.classList.add('hidden'));
confirmHelpBtn.addEventListener('click', () => helpModal.classList.add('hidden'));

searchBtn.addEventListener('click', searchPlace);
searchInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') searchPlace(); });

mapSwitchButtons.forEach(button => {
	button.addEventListener('click', function() {
		const mapType = this.dataset.maptype;
		if (mapType !== currentMapType) initMap(mapType);
	});
});

function updateMapSwitchButtons() {
		mapSwitchButtons.forEach(button => {
		button.classList.toggle('active', button.dataset.maptype === currentMapType);
	});
}

document.addEventListener('click', function(event) {
	const searchContainer = searchInput.closest('.relative');
	if (searchContainer && !searchContainer.contains(event.target)) {
			searchResults.classList.add('hidden');
	}
});

window.onload = function() { 
	initMap('baidu'); 
};
if (speedInput) {
	speedInput.addEventListener('input', updateStats);
}

let sortAsc = true;
document.getElementById('sortPointsBtn').addEventListener('click', function() {
	if (points.length < 2) return;
	if (sortAsc) {
		points.sort((a, b) => a.order - b.order);
	} else {
		points.sort((a, b) => b.order - a.order);
	}
	sortAsc = !sortAsc;
	renderPointList();
	updateMapDisplay(false);
});

document.getElementById('addPointManuallyBtn').addEventListener('click', function() {
	manualNameInput.value = `点${points.length + 1}`;
	manualLngInput.value = '';
	manualLatInput.value = '';
	manualAddPointModal.classList.remove('hidden');
});

manualAddPointCancelBtn.addEventListener('click', function() {
	manualAddPointModal.classList.add('hidden');
});

manualAddPointConfirmBtn.addEventListener('click', function() {
	const name = manualNameInput.value.trim() || `点${points.length + 1}`;
	const lng = parseFloat(manualLngInput.value);
	const lat = parseFloat(manualLatInput.value);
	if (isNaN(lng) || isNaN(lat) || lng < -180 || lng > 180 || lat < -90 || lat > 90) {
		alert('请输入有效的经纬度！');
		return;
	}
	const newPoint = {
		id: Date.now().toString(36) + Math.random().toString(36).substr(2, 5),
		name: name,
		lng: lng,
		lat: lat,
		order: Date.now() + Math.random()
	};
	points.push(newPoint);
	renderPointList();
	updateMapDisplay(false);

	let mapPoint;
	switch (currentMapType) {
		case 'baidu':
			mapPoint = new BMap.Point(newPoint.lng, newPoint.lat);
			break;
		case 'gaode':
			mapPoint = new AMap.LngLat(newPoint.lng, newPoint.lat);
			break;
		case 'tianditu':
			if (typeof T !== 'undefined') {
				mapPoint = new T.LngLat(newPoint.lng, newPoint.lat);
			}
			break;
	}
	if (mapPoint) {
		setMapView([mapPoint]);
	}
	
	manualAddPointModal.classList.add('hidden');
});